#pragma once

/*
	World Spaces are totally seperated worlds, like multiple planets, or multiple dimensions.
	It can also be used for complex cities or dungeons as well.
*/

#include "../../Math/Vec2i.h"
#include <libtcod\libtcod.hpp>
#include <string>
#include <memory>
#include <vector>

typedef std::shared_ptr<TCODParser> TCODParserPtr;
typedef std::unique_ptr<TCODHeightMap> TCODHeightMapUPtr;
typedef std::unique_ptr<TCODRandom> TCODRandomUPtr;
typedef std::unique_ptr<TCODNoise> TCODNoiseUPtr;

template<class T>
struct Vector2d
{
	typedef std::vector<std::vector<T>> Type;
};

namespace World
{
	//Forward declaration
	class WorldCell;
	typedef std::shared_ptr<WorldCell> WorldCellPtr;

	class WorldSpace;
	typedef std::shared_ptr<WorldSpace> WorldSpacePtr;
	typedef std::weak_ptr<WorldSpace> WorldSpaceWPtr;

	class WorldSpaceData
	{
	public:
		int seed;
		std::string name;
		WorldSpaceWPtr parent;

		bool visited;
		bool canFastTravel;

		int waterType;
		float waterHeight;

		Vec2i topLeftCell;
		Vec2i bottomRightCell;
		Vec2i nbCells;
		Vector2d<WorldCellPtr>::Type cells;

		TCODHeightMapUPtr heightmap;
		TCODRandomUPtr ran;
		TCODNoiseUPtr noise;

		WorldSpaceData() : seed(0), visited(false), canFastTravel(false), waterType(0), waterHeight(0.0f) {}
	};
	typedef std::unique_ptr<WorldSpaceData> WorldSpaceDataUPtr;

	//Class declaration
	class WorldSpace
	{
	public:
		WorldSpace();
		~WorldSpace();

		bool isGenerated() const { return (data != nullptr); }
		void generate(const TCODParserPtr &cfg_parser, const std::string &cfg_path);

		void render();

	private:
		WorldSpaceDataUPtr data;
	};

	class WorldCfgParser : public ITCODParserListener
	{
	public:
		WorldCfgParser(WorldSpaceDataUPtr &world_data);
		virtual ~WorldCfgParser();

		bool parserNewStruct(TCODParser *parser,const TCODParserStruct *str,const char *name);
		bool parserFlag(TCODParser *parser,const char *name);
		bool parserProperty(TCODParser *parser,const char *name, TCOD_value_type_t vtype, TCOD_value_t value);
		bool parserEndStruct(TCODParser *parser,const TCODParserStruct *str, const char *name);
		void error(const char *msg);

	private:
		WorldSpaceDataUPtr &world_data;
	};
}
